package com.atguigu.gmall.order.controller;

import com.atguigu.gmall.cart.client.CartFeignClient;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.util.AuthContextHolder;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.model.user.UserAddress;
import com.atguigu.gmall.order.service.OrderService;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.atguigu.gmall.user.client.UserFeignClient;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author atguigu-mqx
 */
@RestController
@RequestMapping("api/order")
public class OrderApiController {

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private CartFeignClient cartFeignClient;

    @Autowired
    private OrderService orderService;

    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;




    //  显示订单页面的数据：
    @GetMapping("auth/trade")
    public Result<Map<String, Object>> trade(HttpServletRequest request){
        //  声明一个map 集合
        HashMap<String, Object> map = new HashMap<>();

        //  获取用户Id
        String userId = AuthContextHolder.getUserId(request);

        //  页面需要 userAddressList detailArrayList tradeNo totalAmount totalNum
        //  页面需要的东西通常在哪个项目中存储? 通常在web-all !
        //  但是，还可以在远程调用存储！
        //  获取收货地址列表！
        List<UserAddress> userAddressList = userFeignClient.findUserAddressListByUserId(userId);
        //  获取送货清单：
        List<CartInfo> cartCheckedList = cartFeignClient.getCartCheckedList(userId);
        //  声明集合
        //        List<OrderDetail> orderDetails = new ArrayList<>();
        //        //  判断
        //        if(!CollectionUtils.isEmpty(cartCheckedList)){
        //            //  循环遍历
        //            //  cartCheckedList.stream().map()
        //            for (CartInfo cartInfo : cartCheckedList) {
        //                OrderDetail orderDetail = new OrderDetail();
        //                orderDetail.setSkuId(cartInfo.getSkuId());
        //
        //                orderDetails.add(orderDetail);
        //            }
        //        }

        //  声明一个变量
        //  final Integer[] skuNum = {0};
        AtomicInteger skuNum = new AtomicInteger();
        List<OrderDetail> orderDetailList = cartCheckedList.stream().map(cartInfo -> {
            //  声明一个订单明细对象
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setSkuId(cartInfo.getSkuId());
            orderDetail.setOrderPrice(cartInfo.getSkuPrice());
            orderDetail.setImgUrl(cartInfo.getImgUrl());
            orderDetail.setSkuName(cartInfo.getSkuName());
            orderDetail.setSkuNum(cartInfo.getSkuNum());

            // skuNum[0] +=cartInfo.getSkuNum();
            skuNum.set(skuNum.get() + cartInfo.getSkuNum());
            //  返回数据
            return orderDetail;
        }).collect(Collectors.toList());

        //  计算总金额
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrderDetailList(orderDetailList);
        //  将计算结果 orderInfo 中的totalAmount 属性
        orderInfo.sumTotalAmount();
        //  保存数据
        map.put("userAddressList",userAddressList);
        map.put("detailArrayList",orderDetailList);
        map.put("totalAmount",orderInfo.getTotalAmount());
        //  两种： 一种：计算集合的长度 ，第二种计算集合中每个商品的skuNum !
        //  map.put("totalNum",orderDetailList.size());
        map.put("totalNum",skuNum);
        //  获取流水号！
        //        String tradeNo = orderService.getTradeNo(userId);
        //        request.setAttribute("tradeNo",tradeNo);
        map.put("tradeNo",orderService.getTradeNo(userId));
        //  返回
        return Result.ok(map);
    }

    //  提交订单的控制器
    //  /auth/submitOrder?tradeNo=' + tradeNo
    //  提交过来的Json 数据，并且有一个tradeNo！
    //  Json --> JavaObject
    //  http://payment.gmall.com/pay.html?orderId=null 页面需要获取到订单Id！根据订单Id 显示支付信息！
    @PostMapping("/auth/submitOrder")
    public Result submitOrder(@RequestBody OrderInfo orderInfo,HttpServletRequest request){
        //  获取用户Id
        String userId = AuthContextHolder.getUserId(request);
        //  调用保存订单方法！
        orderInfo.setUserId(Long.parseLong(userId));
        //  比较：获取页面传递的流水号！
        String tradeNo = request.getParameter("tradeNo");
        //  调用比较方法
        Boolean result = this.orderService.checkTradeNo(tradeNo, userId);
        //  判断
        if (!result){
            //  返回信息提示！
            return Result.fail().message("不能回退无刷新提交订单!");
        }

        //  每个商品都判断：
        //  声明一个集合来存储消息
        List<String> errorList = new ArrayList<>();
        //  声明一个集合来存储线程！
        List<CompletableFuture> completableFutureList = new ArrayList<>();
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        //  判断
        if (!CollectionUtils.isEmpty(orderDetailList)){
            //  循环遍历
            for (OrderDetail orderDetail : orderDetailList) {
                //  验证库存，创建线程
                CompletableFuture<Void> stockCompletableFuture = CompletableFuture.runAsync(() -> {
                    Boolean flag = this.orderService.checkStock(orderDetail.getSkuId(), orderDetail.getSkuNum());
                    if (!flag) {
                        //  返回信息提示！
                        errorList.add(orderDetail.getSkuName() + ":\t没有足够库存!");
                    }
                },threadPoolExecutor);
                //  添加验证库存线程！
                completableFutureList.add(stockCompletableFuture);
                //  验证价格：
                CompletableFuture<Void> priceCompletableFuture = CompletableFuture.runAsync(() -> {
                    //  验证价格：  orderDetail.getOrderPrice()  sku_info price
                    //  return xs != ys ? ((xs > ys) ? 1 : -1) : 0;
                    BigDecimal skuPrice = this.productFeignClient.getSkuPrice(orderDetail.getSkuId());
                    if (skuPrice.compareTo(orderDetail.getOrderPrice()) != 0) {
                        //  价格有变动，最新价格赋值给订单！
                        //  修改购物车中的价格： 将最新的价格赋值给购物车。
                        //  第一种： this.cartFeignClient.xxx(orderDetail.getSkuId()，userId); hget key field hset key field value;
                        //  第二种： this.cartFeignClient.xxx(userId); hvals key 通过提示，用户点击商品详情！
                        //  已选的购物车列表！
                        List<CartInfo> cartCheckedList = this.cartFeignClient.getCartCheckedList(userId);
                        cartCheckedList.forEach(cartInfo -> {
                            //  放入数据就可以了！
                            String cartKey = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
                            this.redisTemplate.opsForHash().put(cartKey, orderDetail.getSkuId().toString(), cartInfo);
                        });
                        //  原来价格：
                        BigDecimal orderPrice = orderDetail.getOrderPrice();
                        BigDecimal amount = orderPrice.subtract(skuPrice);
                        String msg = "";
                        if (amount.intValue() > 0) {
                            msg = "比原来降价:" + amount.abs();
                        } else {
                            msg = "比原来上涨:" + amount.abs();
                        }
                        //  说明价格有变动！
                        errorList.add(orderDetail.getSkuName() + ":\t价格有变动,重新生成订单!" + msg);
                    }
                },threadPoolExecutor);

                //  验证价格的线程添加到集合
                completableFutureList.add(priceCompletableFuture);
            }
        }

        //  任务组合：
        //  int a [] = new int [3];
        CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[completableFutureList.size()])).join();
        //  是否有异常呢？ {"xxx价格变动","xxx库存不足"}
        if(errorList.size()>0){
            return Result.fail().message(StringUtils.join(errorList,","));
        }
        //  删除缓存的流水号
        this.orderService.delTradeNo(userId);
        //  保存订单方法！
        Long orderId = this.orderService.saveOrderInfo(orderInfo);
        //  返回！订单Id！
        return Result.ok(orderId);
    }

    //  查询我的订单 /auth/${page}/${limit}
    @GetMapping("/auth/{page}/{limit}")
    public Result getOrderPageList(@PathVariable Long page,
                                   @PathVariable Long limit,
                                   HttpServletRequest request){
        //  获取用户Id
        String userId = AuthContextHolder.getUserId(request);

        //  调用服务层方法：
        Page queryPage = new Page(page,limit);
        //  根据条件查询分页数据！
        IPage iPage = this.orderService.getOrderPageList(queryPage,userId);
        //  返回数据
        return Result.ok(iPage);
    }

    @GetMapping("inner/getOrderInfo/{orderId}")
    public OrderInfo getOrderInfo(@PathVariable Long orderId){
        //  调用服务层方法：
        return this.orderService.getOrderInfo(orderId);
    }
}
